package com.lonni.rpc.core.socket.codec;

import com.lonni.rpc.core.commom.RpcMsgType;
import com.lonni.rpc.core.model.RpcRequest;
import com.lonni.rpc.core.model.RpcResponse;
import com.lonni.rpc.core.serialize.IRpcSerialize;
import com.lonni.rpc.core.serialize.SerializeFactory;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * 消息解码器
 * 将二进制转换为消息对象
 *
 * @author: Lonni
 * @date: 2024/7/8 0008 16:27
 */
@Slf4j
public class RpcProtocolDecoder extends ByteToMessageDecoder {
    @Override
    protected void decode(ChannelHandlerContext context, ByteBuf byteBuf, List<Object> list) throws Exception {
        //如果消息长度小于头长度 直接返回
        if (byteBuf.readableBytes() < 21) {
            log.info("消息解码器头长度不足;");
            return;
        }
        //标记当前读取位置
        byteBuf.markReaderIndex();
        RpcProtocolHeader header = RpcProtocolHeader.builder()
                .magic(byteBuf.readShort())
                .version(byteBuf.readByte())
                .msgType(byteBuf.readByte())
                .status(byteBuf.readByte())
                .requestId(byteBuf.readLong())
                .serializationType(byteBuf.readInt())
                .msgLen(byteBuf.readInt())
                .build();
        if (byteBuf.readableBytes() < header.getMsgLen()) {
            log.info("消息解码器body长度不足;");
            //回退
            byteBuf.resetReaderIndex();
            return;
        }
        byte[] bodyData = new byte[header.getMsgLen()];
        byteBuf.readBytes(bodyData);
        IRpcSerialize serialize = SerializeFactory.getSerialize(String.valueOf(header.getSerializationType()));
        if (serialize == null) {
            log.error("消息解码器:未找到类型为:{}序列化工具;", header.getSerializationType());
            //回退
            byteBuf.resetReaderIndex();
            return;
        }
        RpcProtocol protocol = new RpcProtocol();
        protocol.setHeader(header);
        //判断是响应还是请求
        RpcMsgType msgType = RpcMsgType.getType(header.getMsgType());
        switch (msgType) {
            case REQUEST:
                RpcRequest request = serialize.deserialize(bodyData, RpcRequest.class);
                protocol.setBody(request);
                break;
            case RESPONSE:
                RpcResponse response = serialize.deserialize(bodyData, RpcResponse.class);
                protocol.setBody(response);
                break;
        }
        list.add(protocol);
    }
}



